package dao;

import model.Store;
import util.*;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.List;

public class StoresManager implements StoresManagement {

    private static List<Store> getResultList(List<Object[]> list)
    {
        List<Store> result = new ResultList<>();
        for(Object[] row : list) result.add(new Store(row));
        return result;
    }

    /**
     * 开店
     * @param creatorID 店主
     * @param storeName 店名
     * @param storePictures 商店图片集信息JSon字符串
     * @return 新店的id，失败返回null
     */
    @Override
    public Long openStore(long creatorID, String storeName, String storePictures)
    {
        if(Common.isStringEmpty(storeName)) return null;
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            Object st_id = conn.updateForGeneratedKey("insert into t_stores(st_id, u_id, st_name, st_ctime, st_bank, st_state, st_pic_address) values(null, ?, ?, CURRENT_TIMESTAMP, 0.00, '营业', ?)", creatorID, storeName, storePictures);
            JDBCFactory.returnBack(conn);

            if(st_id == null) return null;
            return ((BigInteger)st_id).longValue();
        } catch(SQLException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    @Override
    public boolean alterStore(long storeID, Store target)
    {
        if(target == null) return false;
        try {
            boolean firstArg = true;
            StringBuilder sql_set = new StringBuilder();
            List<Object> args = new ArgsList<>();

            if(!Common.isStringEmpty(target.getSt_name())) {
                sql_set.append(" st_name = ?");
                args.add(target.getSt_name());
                firstArg = false;
            }

            if(!Common.isStringEmpty(target.getSt_state())) {
                if(!firstArg) sql_set.append(',');
                sql_set.append(" st_state = ?");
                args.add(target.getSt_state());
                firstArg = false;
            }

            if(!Common.isStringEmpty(target.getSt_pic_address())) {
                if(!firstArg) sql_set.append(',');
                sql_set.append(" st_pic_address = ?");
                args.add(target.getSt_pic_address());
            }

            args.add(storeID);

            JDBCConnection conn = JDBCFactory.takeJDBC();
            int count = conn.update(args, "update t_stores set" + sql_set + " where st.id = ?");
            JDBCFactory.returnBack(conn);

            return count > 0;
        } catch(SQLException e) {
            System.err.println(e.getMessage());
            return false;
        }
    }

    @Override
    public int closeStoreByCreator(long creatorID)
    {
        JDBCConnection conn = JDBCFactory.takeJDBC();
        try {
            conn.start();
            int count = conn.update("update t_goods tg set tg.g_status = '下架' where exists(select ts.st_id from t_stores ts where ts.u_id = ? and ts.st_id = tg.st_id)", creatorID);
            if(conn.update("update t_stores set st_state = '关闭' where u_id = ?", creatorID) == 0) {
                throw new SQLException("关闭店铺失败：事务失败。");
            }
            conn.commit();
            JDBCFactory.returnBack(conn);
            return count;
        } catch(SQLException e) {
            System.err.println(e.getMessage());
            return 0;
        }
    }

    @Override
    public int closeStore(long storeID)
    {
        JDBCConnection conn = JDBCFactory.takeJDBC();
        try {
            conn.start();
            int count = conn.update("update t_goods set g_status = '下架' where st_id = ?", storeID);
            if(conn.update("update t_stores set st_state = '关闭' where st_id = ?", storeID) == 0) {
                throw new SQLException("关闭店铺失败：事务失败。");
            }
            conn.commit();
            JDBCFactory.returnBack(conn);
            return count;
        } catch(SQLException e) {
            conn.rollback();
            System.err.println(e.getMessage());
            return 0;
        }
    }

    /**
     * 店铺收入，应在订单完成结算时由订单管理模块调用
     * @param storeID 店铺id
     * @param cash 平台抽成后赚取的收益
     * @return 成功返回true，失败返回false
     */
    boolean earn(long storeID, BigDecimal cash)
    {
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            int count = conn.update("update t_stores set st_bank = st_bank + ? where st_id = ?", cash, storeID);
            JDBCFactory.returnBack(conn);
            return count > 0;
        } catch(SQLException e) {
            System.err.println(e.getMessage());
            return false;
        }
    }

    /**
     * 店铺提现
     * @param storeId 店铺id
     * @param cash 提现金额
     * @return 成功返回true，失败返回false
     */
    @Override
    public boolean withdrawalByStore(long storeId, BigDecimal cash)
    {
        JDBCConnection conn = null;
        try {
            conn = JDBCFactory.takeJDBC();
            conn.start();

            List<Object[]> list = conn.query("select * from t_stores t where t.st_id = ?", storeId);
            Store s = null;
            if(list == null  ||  list.size() == 0 ) throw new SQLException("提现失败：不存在该店铺");
            else {
                s = new Store(list.get(0));
                if(s.getSt_bank().compareTo(cash) < 0) throw new SQLException("提现失败：店铺资金不足");
            }

            int count = conn.update("update t_stores set st_bank = st_bank - ? where st_id = ?", cash, storeId);
            count &= conn.update("update t_users set u_bank = u_bank + ? where u_id = ?", cash, s.getU_id());

            conn.commit();
            JDBCFactory.returnBack(conn);
            conn = null;
            return count != 0;
        } catch(SQLException e) {
            conn.rollback();
            JDBCFactory.returnBack(conn);

            System.err.println(e.getMessage());
            return false;
        }
    }

    /**
     * 店铺提现 - 全部提现
     * @param storeId 店铺id
     * @return 成功返回true，失败返回false
     */
    @Override
    public boolean withdrawalByStore(long storeId)
    {
        JDBCConnection conn = null;
        try {
            conn = JDBCFactory.takeJDBC();
            conn.start();

            List<Object[]> list = conn.query("select * from t_stores t where t.st_id = ?", storeId);
            Store s = null;
            if(list == null  ||  list.size() == 0 ) throw new SQLException("提现失败：不存在该店铺");
            else {
                s = new Store(list.get(0));
                if(s.getSt_bank().compareTo(new BigDecimal("0.00")) <= 0) throw new SQLException("提现失败：店铺资金不足");
            }

            int count = conn.update("update t_users set u_bank = u_bank + ? where u_id = ?", s.getSt_bank(), s.getU_id());
            count &= conn.update("update t_stores set st_bank = 0.00 where st_id = ?", storeId);

            conn.commit();
            JDBCFactory.returnBack(conn);
            conn = null;
            return count != 0;
        } catch(SQLException e) {
            conn.rollback();
            JDBCFactory.returnBack(conn);

            System.err.println(e.getMessage());
            return false;
        }
    }

    /**
     * 店铺提现 - 全部提现
     * @param uId 店主id
     * @return 成功返回提现的总金额（包括0.00），异常返回null
     */
    @Override
    public BigDecimal withdrawalByCreator(long uId)
    {
        JDBCConnection conn = null;
        try {
            BigDecimal sum = new BigDecimal("0.00");
            List<Object[]> list = null;

            conn = JDBCFactory.takeJDBC();
            conn.start();
            list = conn.query("select * from t_stores t where t.u_id = ?", uId);

            if(list == null  ||  list.size() == 0) throw new SQLException("提现失败：未找到该用户名下注册的店铺");

            for(Object[] row : list) {
                sum = sum.add(new Store(row).getSt_bank());
            }

            conn.update("update t_users set u_bank = u_bank + ? where u_id = ?", sum, uId);
            if(conn.update("update t_stores set st_bank = 0.00 where u_id = ?", uId) <= 0) {
                throw new SQLException("提现失败：出现未知异常");
            }

            conn.commit();
            JDBCFactory.returnBack(conn);
            conn = null;
            return sum;

        } catch(SQLException e) {
            conn.rollback();
            JDBCFactory.returnBack(conn);
            System.err.println(e.getMessage());
            return null;
        }
    }

    @Override
    public List<Store> findAll(int pageSize, int page) {
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            List<Store> list = conn.queryEntities(Store.class, "select * from t_stores limit ?, ?", (page - 1) * pageSize, pageSize);
            JDBCFactory.returnBack(conn);

            return list;
        } catch(SQLException | NoSuchMethodException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    @Override
    public List<Store> findByTime(LocalDateTime begintime, LocalDateTime endtime) {
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            List<Store> list = conn.queryEntities(Store.class, "select * from t_stores t where t.st_ctime between ? and ?", begintime, endtime);
            JDBCFactory.returnBack(conn);

            return list;
        } catch(SQLException | NoSuchMethodException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    @Override
    public List<Store> findByCreator(long creatorUId) {
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            List<Store> list = conn.queryEntities(Store.class, "select * from t_stores t where t.u_id = ?", creatorUId);
            JDBCFactory.returnBack(conn);
            return list;
        } catch(SQLException | NoSuchMethodException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    @Override
    public Store findById(long storeId) {
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            List<Store> list = conn.queryEntities(Store.class,"select * from t_stores t where t.st_id = ?", storeId);
            JDBCFactory.returnBack(conn);

            if(list != null  ||  list.size() == 1) return list.get(0);
            return null;
        } catch(SQLException | NoSuchMethodException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    public static void main(String[] args) {
    }
}
